/**
 * @mainpage
 * @par O programie:
 * bananaloader to bootloader dla procesorów avr. W tej wersji do jego obsługi potrzebny jest jedynie terminal. Za jego pomocą wydajemy polecenia oraz przesyłamy plik hex. Jest to bardzo wygodne ale należy pamiętać, że uzyskane jest to kosztem objętości programu. Cały kod odpowiedzialny za konwersję pliku hex jest zawarty w pamięci mikrokontrolera. Tej wady pozbawiona jest inna wersja bootloadera zawierająca dodatkowy program na PC.
 * @par Licencja
 * GPL
 * @author Michał Banasiak
 * @date 14.05.2011
 * @version 0.1
 * @par Strona projektu
 * http://www.bananaloader.googlecode.com
 * @par Repozytorium svn
 * https://bananaloader.googlecode.com/svn
 * @par Contact:
 * Mój email: @a m.banasiakataol.pl
 * @par Kompilacja
 * Instukcja konfiguracji i kompilacji na stronie @ref komp
 * @par Sposób użycia
 * na stronie @ref sposob.
 */

/**
 * @page komp Kompilacja
 * W pliku Makefile istnieje następująca sekcja:
 * @code
 * ##################################################################
 * # bananaloader - ustawienia
 * #
 * # Adres bootloadera
 * BLS_START = 0x1800 #atmega8
 * #BLS_START = 0x7000 #atmega32
 * # Nazwa procesora
 * MCU = atmega8
 * # Czestotliwosc taktowania
 * F_CPU = 14745600
 * # Szybkosc UART
 * UART_BAUD = 57600
 * # czas oczekiwania na wyslanie checi zaprogramowania procesora (w sekundach) (min. 1s)
 * BOOT_TIME = 10
 * ##################################################################
 * @endcode
 * W tej sekcji konfigurujemy program przed kompilacją. Mamy tutaj 5 zmiennych do ustawienia.
 * @par BLS_START
 * przechowuje adres bootloadera. Jest to informacja dla linkera. Adres możemy znaleźć w nocie katalogowej danego mikrokontrolera. Kod odpowiedzialny za umieszczenie programu w odpowiednim miejscu w pamięci jest przedstawiony poniżej.
 * @code
 * LDFLAGS += -Wl,--section-start=.text=$(BLS_START)
 * @endcode
 * @par MCU
 * Zmienna przechowująca nazwę mikrokontrolera. Informacja potrzebna gcc.
 * @par F_CPU
 * Częstotliwość taktowania procesora w Hz.
 * @par UART_BAUD
 * Szybkość działania UART.
 * @par BOOT_TIME
 * Bootloader po włączeniu zasilania czeka na sygnał użytkownika przez pewien czas. Ten czas (w sekundach) przechowuje zmienna BOOT_TIME.
 *
 * Linker dostaje jeszcze jedną bardzo ważną informację. Przedstawia to fragment kodu poniżej.
 * @code
 * LDFLAGS += -nostartfiles
 * @endcode
 * Opcja nostartfiles wyłącza inicjalizację stosu i wektora przerwań. Również skok do funcji main jest wyłączony. W kodzie programu jset dodana ręcznie inicjalizacja stosu oraz skok do main. Rezygnacja z możliwości obsługi przerwań znacznie odchudza plik wynikowy.

*/


/**
 * @page sposob Sposób użycia
 * @par Terminal
 * Do obsługi programu potrzeba terminala z obsługą kontroli przepływu XON/XOFF. Terminal należy skonfigurować tak, by czas pomiędzy wysyłanymi znakami pliku był nie mniejszy niż 30ms. Szybkość transmisji ustawiamy tak jak w pliku Makefile (@ref komp).
 * @par Komunikacja z bootloaderem
 * Po resecie procesora bootloader przez ustalony czas, co sekundę wysyła kropkę. Czas ustalamy w pliku Makefile(@ref komp). W tym czasie należy wyslać znak 'x'. Gdy czas minie jest wykonywany skok do właściwego programu. Oczywiście jeśli procesor jest świeży i ma wgrany tylko bootloader licznik programu szybko przeskoczy całą pamięć, gdzie powinien znajdować się program i bootloader zostanie uruchomiony ponownie.
 * @par Wysyłanie programu
 * Po wysłaniu znaku 'x', program czeka na wysłanie pliku hex. Prawidłowy odbiór oraz zapis w pamięci mikrokontrolera każdej linii jest potwierdzany znakiem 'X'. Po zakończeniu pracy bootloadera jest przesyłany znak 'K' oraz wykonywany skok do właściwego programu.
 */

#include "bananaloader.h"
#include "rs232.h"

/**
 * Dodanie atrybutu noreturn powoduje odchudzenie pliku wynikowego o kilka bajtow.
 */
int
main(void)
__attribute__ (( noreturn ));

int main(void)
{
    /* Inicjalizacja RS232 */
    USART_Start();

    /* deklaracja zmiennych */
    uint8_t Received_Char=0;
    ilosc=0;
    aktualny=0;

    /* Odczekaj chwile po uruchomieniu */
    for (int i=0; i<200; i++) _delay_ms(5);

    /* Zezwolenie na transmisje */
    USART_Transmit(XON);

    /* wysylanie znaku '.' do odebrania znaku 'x' lub uplyniecia czasu
        * oczekiwania */
    for (int i=0; i<BOOT_TIME; i++)
    {
        if ( (UCSRA & _BV(RXC) ) )
        {
            Received_Char = UDR;
            break;
        }
        else
        {
            USART_Transmit('.');
            for (int i=0; i<200; i++) _delay_ms(5);
        }
    }

    /* Koniec zezwolenia */
    USART_Transmit(XOFF);

    if ( Received_Char == 'x' )
    {
        /* Oczekiwanie na zakonczenie opracji na pamieci */
        boot_spm_busy_wait();

        /* Wykasowanie calej pamieci programu*/
        Erase_All_Memory();

        /* Wgranie programu */
        Memory_Programming();
    }

    /* Znak informujacy o zakonczeniu pracy bootloadera */
    _delay_ms(10);
    USART_Transmit('K');

    /* Odblokowanie sekcji Read-While-Write */
    boot_rww_enable();

    /* Wylaczenie interfejsu UART */
    UCSRB = 0;

    /* skok do wla彡iwego programu */
    jump0();

    while (1);
}
